//
// Description: 859. Kruskal算法求最小生成树
// Created by Loading on 2022/5/22.
//

#include <bits/stdc++.h>

using namespace std;

constexpr int N = 2e5 + 10;
constexpr int INF = 0x3f3f3f3f;

int father[N]; // 祖先节点
int n, m;

struct Edges {
    int a, b, w;

    bool operator<(const Edges &E) const {
        return w < E.w;
    }
} edges[N];

// 查找 x 的祖先节点 + 路径压缩
int find(int x) {
    if (father[x] != x) {
        father[x] = find(father[x]);
    }
    return father[x];
}

int kruskal() {
    // 初始化祖先节点
    for (int i = 1; i <= n; ++i) {
        father[i] = i;
    }
    // 将边按权重排序
    sort(edges, edges + m);

    int res = 0; // 最小生成树中所有边的权重之和
    int cnt = 0; // 集合中有多少条边
    // 遍历每条边
    for (int i = 0; i < m; ++i) {
        int a = edges[i].a;
        int b = edges[i].b;
        int w = edges[i].w;
        // 寻找两个节点的祖先节点
        a = find(a), b = find(b);
        if (a != b) {
            father[a] = b;
            res += w;
            ++cnt;
        }
    }

    // 集合中的边数 < n - 1，必然不连通
    if (cnt < n - 1) {
        return INF;
    }
    return res;
}

int main() {
    cin >> n >> m;
    for (int i = 0; i < m; ++i) {
        int u, v, w;
        cin >> u >> v >> w;
        edges[i] = {u, v, w};
    }

    int res = kruskal();
    if (res == INF) {
        puts("impossible");
    } else {
        cout << res << endl;
    }

    return 0;
}